{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "\n",
    "# 设置 matplotlib 使用支持中文的字体\n",
    "# 'Microsoft YaHei' 是 Windows 系统中常见的字体\n",
    "# 如果您使用 macOS，可以尝试 'PingFang SC'\n",
    "# 如果您使用 Linux，可以尝试 'WenQuanYi Micro Hei'\n",
    "plt.rcParams['font.sans-serif'] = ['Microsoft YaHei'] \n",
    "\n",
    "# 解决负号 '-' 显示为方块的问题\n",
    "plt.rcParams['axes.unicode_minus'] = False \n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Jupyter笔记本中的可共享性问题\n",
    "\n",
    "这个笔记本演示了Jupyter在共享和部署方面的困难：\n",
    "1. 难以部署为Web应用\n",
    "2. 交互性在静态分享中丢失\n",
    "3. 需要复杂的基础设施"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 问题1：无法直接部署为Web应用\n",
    "\n",
    "Jupyter笔记本主要设计用于开发环境，不是为最终用户设计的"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "import ipywidgets as widgets\n",
    "from IPython.display import display\n",
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "import pandas as pd"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 创建一个交互式数据分析界面"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "ef60560977c441fd8a7eb8e1b7d754fe",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "IntSlider(value=100, description='样本大小:', max=1000, min=50, step=50)"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "387bd8a3520d42c68118dede4ef01b75",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "FloatSlider(value=0.1, description='噪声水平:', max=1.0, step=0.05)"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "dcfc5e4c362445dd990874d6cb86646c",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Dropdown(description='图表类型:', options=('散点图', '直方图', '箱线图'), value='散点图')"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 数据生成参数\n",
    "sample_size = widgets.IntSlider(\n",
    "    value=100,\n",
    "    min=50,\n",
    "    max=1000,\n",
    "    step=50,\n",
    "    description='样本大小:'\n",
    ")\n",
    "\n",
    "noise_level = widgets.FloatSlider(\n",
    "    value=0.1,\n",
    "    min=0,\n",
    "    max=1,\n",
    "    step=0.05,\n",
    "    description='噪声水平:'\n",
    ")\n",
    "\n",
    "chart_type = widgets.Dropdown(\n",
    "    options=['散点图', '直方图', '箱线图'],\n",
    "    value='散点图',\n",
    "    description='图表类型:'\n",
    ")\n",
    "\n",
    "display(sample_size, noise_level, chart_type)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "b0ac61639229422a965142bca459bfec",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Output()"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 输出区域\n",
    "output = widgets.Output()\n",
    "\n",
    "def update_analysis(change=None):\n",
    "    with output:\n",
    "        output.clear_output(wait=True)\n",
    "        \n",
    "        # 生成数据\n",
    "        size = sample_size.value\n",
    "        noise = noise_level.value\n",
    "        \n",
    "        np.random.seed(42)  # 为了可重现性\n",
    "        x = np.linspace(0, 10, size)\n",
    "        y = 2 * x + 1 + np.random.normal(0, noise * 5, size)\n",
    "        \n",
    "        data = pd.DataFrame({'X': x, 'Y': y})\n",
    "        \n",
    "        # 创建图表\n",
    "        fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))\n",
    "        \n",
    "        chart = chart_type.value\n",
    "        if chart == '散点图':\n",
    "            ax1.scatter(data['X'], data['Y'], alpha=0.6)\n",
    "            ax1.set_xlabel('X')\n",
    "            ax1.set_ylabel('Y')\n",
    "            ax1.set_title('X vs Y 散点图')\n",
    "        elif chart == '直方图':\n",
    "            ax1.hist(data['Y'], bins=20, alpha=0.7)\n",
    "            ax1.set_xlabel('Y值')\n",
    "            ax1.set_ylabel('频次')\n",
    "            ax1.set_title('Y值分布直方图')\n",
    "        else:  # 箱线图\n",
    "            ax1.boxplot([data['X'], data['Y']], labels=['X', 'Y'])\n",
    "            ax1.set_title('X和Y的箱线图')\n",
    "        \n",
    "        # 统计信息\n",
    "        ax2.axis('off')\n",
    "        stats_text = f\"\"\"\n",
    "        数据统计信息:\n",
    "        \n",
    "        样本大小: {size}\n",
    "        噪声水平: {noise:.2f}\n",
    "        \n",
    "        X统计:\n",
    "        均值: {data['X'].mean():.2f}\n",
    "        标准差: {data['X'].std():.2f}\n",
    "        \n",
    "        Y统计:\n",
    "        均值: {data['Y'].mean():.2f}\n",
    "        标准差: {data['Y'].std():.2f}\n",
    "        \n",
    "        相关系数: {data['X'].corr(data['Y']):.3f}\n",
    "        \"\"\"\n",
    "        ax2.text(0.1, 0.9, stats_text, transform=ax2.transAxes, \n",
    "                fontsize=10, verticalalignment='top')\n",
    "        \n",
    "        plt.tight_layout()\n",
    "        plt.show()\n",
    "\n",
    "# 绑定事件\n",
    "sample_size.observe(update_analysis, names='value')\n",
    "noise_level.observe(update_analysis, names='value')\n",
    "chart_type.observe(update_analysis, names='value')\n",
    "\n",
    "# 初始显示\n",
    "update_analysis()\n",
    "\n",
    "display(output)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 添加数据导出功能"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "5f6dadca66f44f4c86f223a412e366d3",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Button(button_style='success', description='导出数据', style=ButtonStyle())"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "392731921f4c4500bc19da95ecacbba1",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Output()"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "export_button = widgets.Button(\n",
    "    description='导出数据',\n",
    "    button_style='success'\n",
    ")\n",
    "\n",
    "export_output = widgets.Output()\n",
    "\n",
    "def export_data(button):\n",
    "    with export_output:\n",
    "        export_output.clear_output(wait=True)\n",
    "        \n",
    "        # 重新生成当前数据\n",
    "        size = sample_size.value\n",
    "        noise = noise_level.value\n",
    "        \n",
    "        np.random.seed(42)\n",
    "        x = np.linspace(0, 10, size)\n",
    "        y = 2 * x + 1 + np.random.normal(0, noise * 5, size)\n",
    "        \n",
    "        data = pd.DataFrame({'X': x, 'Y': y})\n",
    "        \n",
    "        # 在实际应用中，这里会保存到文件\n",
    "        print(f\"数据已导出 (模拟)\")\n",
    "        print(f\"文件名: data_sample_{size}_noise_{noise:.2f}.csv\")\n",
    "        print(f\"数据预览:\")\n",
    "        print(data.head())\n",
    "\n",
    "export_button.on_click(export_data)\n",
    "\n",
    "display(export_button, export_output)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**问题说明**：\n",
    "\n",
    "上面创建了一个有用的交互式数据分析工具，但是：\n",
    "\n",
    "1. **无法直接部署**：不能简单地将这个笔记本部署为Web应用供其他人使用\n",
    "2. **需要Jupyter环境**：用户必须安装并运行Jupyter才能使用\n",
    "3. **复杂的部署流程**：需要使用Voilà、Binder或其他工具，配置复杂\n",
    "4. **性能问题**：在Web部署时性能通常不佳\n",
    "5. **安全考虑**：直接暴露Jupyter环境存在安全风险"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 问题2：静态分享丢失交互性"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "39a816f7cdd44f01adfcdc303c0c4fd1",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "interactive(children=(FloatSlider(value=1.0, description='freq', max=5.0, min=0.5), FloatSlider(value=1.0, des…"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 这个交互式组件在静态分享中完全无用\n",
    "interactive_demo = widgets.interact(\n",
    "    lambda freq, amplitude: plt.plot(\n",
    "        np.linspace(0, 2*np.pi, 100),\n",
    "        amplitude * np.sin(freq * np.linspace(0, 2*np.pi, 100))\n",
    "    ) or plt.title(f'正弦波: 频率={freq}, 振幅={amplitude}') or plt.show(),\n",
    "    freq=widgets.FloatSlider(min=0.5, max=5, step=0.1, value=1),\n",
    "    amplitude=widgets.FloatSlider(min=0.1, max=2, step=0.1, value=1)\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**静态分享的问题**：\n",
    "\n",
    "1. **GitHub渲染**：在GitHub上查看时，所有交互元素都不工作\n",
    "2. **nbviewer**：即使使用nbviewer，交互性也会丢失\n",
    "3. **PDF导出**：转换为PDF时只能看到静态快照\n",
    "4. **邮件分享**：通过邮件分享的HTML版本没有交互性\n",
    "\n",
    "用户只能看到代码和最后一次运行的输出，无法体验交互功能。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 问题3：复杂的部署基础设施"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**要将Jupyter笔记本部署为Web应用，需要**：\n",
    "\n",
    "### 选项1：使用Voilà\n",
    "```bash\n",
    "pip install voila\n",
    "voila notebook.ipynb --port=8866\n",
    "```\n",
    "**问题**：\n",
    "- 需要额外安装和配置\n",
    "- 性能不佳\n",
    "- 定制化困难\n",
    "- 错误处理不友好\n",
    "\n",
    "### 选项2：使用Binder\n",
    "**问题**：\n",
    "- 启动时间长（几分钟）\n",
    "- 资源限制\n",
    "- 不适合生产环境\n",
    "- 依赖外部服务\n",
    "\n",
    "### 选项3：自建JupyterHub\n",
    "**问题**：\n",
    "- 复杂的基础设施要求\n",
    "- 安全配置困难\n",
    "- 维护成本高\n",
    "- 扩展性问题\n",
    "\n",
    "### 选项4：转换为其他框架\n",
    "**问题**：\n",
    "- 需要重写代码（如转换为Streamlit、Dash等）\n",
    "- 丢失原有的开发体验\n",
    "- 维护两套代码"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 总结\n",
    "\n",
    "Jupyter笔记本在可共享性方面的主要问题：\n",
    "\n",
    "1. **部署复杂**：需要额外工具和复杂配置\n",
    "2. **交互性丢失**：静态分享无法保持交互功能\n",
    "3. **性能问题**：Web部署时性能通常不佳\n",
    "4. **安全风险**：直接暴露开发环境\n",
    "5. **维护困难**：需要管理复杂的部署基础设施\n",
    "6. **用户体验差**：最终用户需要技术知识才能使用\n",
    "\n",
    "这些问题使得Jupyter笔记本主要适合开发和探索，而不适合作为最终产品分享给非技术用户。"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "marimo-ui (3.12.11)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.11"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
